package com.hrt.common.safe.token;

import com.btcode.exception.BusinessException;
import com.btcode.security.ThreeDESUtil;
import com.hrt.common.safe.IUser;
import com.hrt.common.safe.UserSafeService;
import com.hrt.common.safe.user.UserStatus;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * <pre>
 * token登录支持
 * token信息中包含三部分内容：
 * [_secretCode],[userid],[generateTime]
 *  比如：hollytech,234-hhh-jasdf-23f-af4-gsd,2018-7-20 10:00:36
 * secretCode:是密码部分，如果前端传过来不包含这部分，或者这部分信息不对，则认为非法
 * userid:用户的id,用于校验用户是否存在，如果不存在，也认为是非法
 * generateTime:token生成的时间，如果格式错误，或者生成的时间已经超过8小时，则认为是非法
 * </pre>
 *
 * @author gislin
 */
public abstract class TokenService {

    private static final String secretCode = "hollytech";
    private static final String dateFormat = "yyyy-MM-dd HH:mm:ss";
    private static final int tokenInfoLength = 3;

    /**
     * 8小时过期
     */
    private static final long expiredTime = 1000 * 60 * 60 * 1;

    public static String encode(IUser userModel) {
        String userId = userModel.getId();
        return encodeStr(userId);
    }

    public static IUser decodeToken(String token) throws Exception {

        String userId = decodeStr(token);

        IUser userModel = UserSafeService.getInstance(UserSafeService.class).getUser(userId);

        if (userModel == null) {
            throw new TokenDecodeException("非法token,用户信息不存在");
        }

        if (UserStatus.Disable.equals(userModel.getStatus())) {
            throw new TokenDecodeException("用户已停用");
        }

        return userModel;

    }

	/**
     * 将指定字符串加密为token
     */
    public static String encodeStr(String str) {
        SimpleDateFormat sf = new SimpleDateFormat(dateFormat);

        String dateStr = sf.format(new Date());

        String info = secretCode + "," + str + "," + dateStr;
        String token = null;
        try {
            token = ThreeDESUtil.encode(info);
        }
        catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException("生成token出错", e);
        }
        return token;
    }

	/**
     * 解密并提取token中的信息
     */
    public static String decodeStr(String token) throws Exception {
        String decodeStr = ThreeDESUtil.decode(token);
        String[] infos = decodeStr.split(",");

        if (infos.length != tokenInfoLength) {
            throw new TokenDecodeException("非法token,信息不足");
        }

        String secretCode = infos[0];

        if (!secretCode.equals(secretCode)) {
            throw new TokenDecodeException("非法token,密码不对");
        }

        String str = infos[1];
        String generateTimeStr = infos[2];

        SimpleDateFormat sf = new SimpleDateFormat(dateFormat);

        try {
            Date generateTime = sf.parse(generateTimeStr);
            Date now = new Date();
            if (now.getTime() - generateTime.getTime() > expiredTime) {
                throw new TokenDecodeException("非法token,已过期");
            }
        }
        catch (Exception e) {
            throw new TokenDecodeException("非法token,非法时间");
        }
        return str;
    }
}
